﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.Revit;
using YJKArchMethodLibrary.Utils;
using Parapet.Previewer;
using TopologySearch;


namespace Parapet.Forms
{
	public partial class ParapetForm : System.Windows.Forms.Form
	{
		public ParapetForm.FormResultStyle ResultStyle
		{
			get
			{
				return this.m_ResultStyle;
			}
		}

		public bool IsReadHistoryDataValid { get; set; }

		public ParapetForm(ParapetForm.FormStyle style, ExternalCommandData cmdData)
		{
			this.IsReadHistoryDataValid = true;
			this.m_cmdData = cmdData;
			this.m_FormStyle = style;
			this.m_Doc = cmdData.Application.ActiveUIDocument.Document;
			this.InitializeComponent();
			this.cmbCoping.DisplayMember = "FamilySymbolName";
            this.m_MainPreviewer = new Parapet.Previewer.Previewer(this, this.pnlPreview.Left + this.pnlPreview.Parent.Left, this.pnlPreview.Top, this.pnlPreview.Width, this.pnlPreview.Height, 1u);
			base.MouseWheel += this.m_MainPreviewer.MouseWheel;
		}

		public ParapetForm.ParapetData GetParapetData()
		{
			ParapetForm.ParapetData parapetData = new ParapetForm.ParapetData();
			parapetData.TypeName = this.tbName.Text;
			parapetData.Height = AssistFunc.mmToFeet(Convert.ToDouble(this.m_StrHeight));
			parapetData.Thickness = AssistFunc.mmToFeet(Convert.ToDouble(this.m_StrThickness));
			parapetData.HasCoping = this.chkbCoping.Checked;
			parapetData.CopingStyleIndex = this.cmbCoping.SelectedIndex;
			parapetData.CopingStyleName = this.cmbCoping.SelectedItem.ToString();
			parapetData.UserProfileCvs = null;
			if (this.cmbCoping.SelectedIndex < 4)
			{
				return parapetData;
			}
			List<Curve> list = null;
			if (this.mapFamilyName2Cvs.ContainsKey(parapetData.CopingStyleName))
			{
				list = this.mapFamilyName2Cvs[parapetData.CopingStyleName];
			}
			else
			{
				Document document = null;
				try
				{
					string text = ParapetForm.InitUserParapetFilePathWithVersion() + "\\" + parapetData.CopingStyleName + ".rfa";
					document = this.m_Doc.Application.OpenDocumentFile(text);
					FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
					List<CurveElement> list2 = filteredElementCollector.OfClass(typeof(CurveElement)).Cast<CurveElement>().ToList<CurveElement>();
					list = new List<Curve>();
					foreach (CurveElement curveElement in list2)
					{
						IList<XYZ> list3 = curveElement.GeometryCurve.Tessellate();
						for (int i = 0; i < list3.Count - 1; i++)
						{
							list.Add(Line.CreateBound(list3[i], list3[i + 1]));
						}
					}
					List<List<Curve>> boundaryCurves = this.GetBoundaryCurves(this.m_cmdData, list);
					if (boundaryCurves.Count > 0)
					{
						list = boundaryCurves.First<List<Curve>>();
						this.mapFamilyName2Cvs.Add(parapetData.CopingStyleName, list);
					}
				}
				catch
				{
				}
				finally
				{
					if (document != null)
					{
						document.Close(false);
					}
				}
			}
			parapetData.UserProfileCvs = list;
			return parapetData;
		}

		private List<List<Curve>> GetBoundaryCurves(ExternalCommandData cmdData, List<Curve> curves)
		{
			int num = 0;
			List<Pole2D> list = new List<Pole2D>();
			foreach (Curve curve in curves)
			{
				Pole2D item = Pole2D.TransformWallToStructure2DPole(curve, new ElementId(num++), 0.0, 0.0);
				list.Add(item);
			}
			List<List<Curve>> result = new List<List<Curve>>();
			try
			{
				StructureLoopSearcher structureLoopSearcher = new StructureLoopSearcher(cmdData, 1E-06);
				result = structureLoopSearcher.GetCellsEdgeLoops(list, false);
			}
			catch (Exception)
			{
			}
			return result;
		}

		public void SetParapetData(ParapetForm.ParapetData data)
		{
			this.tbName.Text = data.TypeName;
			this.m_StrHeight = AssistFunc.feetToMM(data.Height).ToString("f0");
			this.tbHeight.Text = this.m_StrHeight;
			this.m_StrThickness = AssistFunc.feetToMM(data.Thickness).ToString("f0");
			this.tbThickness.Text = this.m_StrThickness;
			this.chkbCoping.Checked = data.HasCoping;
			int num = this.cmbCoping.FindString(data.CopingStyleName);
			if (num > -1)
			{
				this.cmbCoping.SelectedIndex = num;
			}
		}

		public static string InitUserParapetFilePathWithVersion()
		{
			string text = Path.Combine(@"C:\Hongye\HYArch2018", ParapetForm.strFamilyFolderName, RevitVersion.Version);
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			return text;
		}

		private void InitParapetInfo()
		{
			this.cmbCoping.Items.Clear();
			this.cmbCoping.Items.Clear();
			this.cmbCoping.Items.Add("88J14-2 W8 1");
			this.cmbCoping.Items.Add("88J14-2 W8 2");
			this.cmbCoping.Items.Add("88J14-2 W8 3");
			this.cmbCoping.Items.Add("88J14-2 W8 4");
			this.cmbCoping.SelectedIndex = 0;
			string path = ParapetForm.InitUserParapetFilePathWithVersion();
			DirectoryInfo directoryInfo = new DirectoryInfo(path);
			foreach (FileInfo fileInfo in directoryInfo.GetFiles("*.rfa", SearchOption.TopDirectoryOnly))
			{
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.Name);
				this.cmbCoping.Items.Add(fileNameWithoutExtension);
			}
		}

		protected override void DefWndProc(ref Message m)
		{
			int msg = m.Msg;
			if (msg == 1125)
			{
				if (m.WParam.ToInt32() != 1)
				{
					return;
				}
                List<Parapet.Previewer.CurveInfo> curves = new List<Parapet.Previewer.CurveInfo>();
                List<Parapet.Previewer.TextNoteInfo> textNotes = new List<Parapet.Previewer.TextNoteInfo>();
                List<Parapet.Previewer.FillRegion> fillRegions = new List<Parapet.Previewer.FillRegion>();
				try
				{
					this.GetProfileCurves(ref curves, ref textNotes, ref fillRegions);
					this.m_MainPreviewer.Curves = curves;
					this.m_MainPreviewer.TextNotes = textNotes;
					this.m_MainPreviewer.FillRegions = fillRegions;
					return;
				}
				catch (Exception)
				{
					return;
				}
			}
			base.DefWndProc(ref m);
		}

		private void GetProfileCurves(ref List<CurveInfo> curvesInfoList, ref List<TextNoteInfo> textNoteInfoList, ref List<FillRegion> fillRegions)
		{
			this.m_ParapetProfileDrawingKit.DrawProfile(this.GetParapetData(), ref curvesInfoList, ref textNoteInfoList, ref fillRegions);
		}

		private void ParapetForm_Load(object sender, EventArgs e)
		{
			//base.Icon = Resource.YArchitechIcon;
			if (this.m_FormStyle == ParapetForm.FormStyle.FS_CREATE)
			{
				this.Text = "自动创建女儿墙";
				this.btnEditBaseLine.Visible = false;
				this.btnEditWall.Visible = false;
				this.tbName.Enabled = true;
			}
			else if (this.m_FormStyle == ParapetForm.FormStyle.FS_EDITWALL)
			{
				this.Text = "编辑女儿墙";
				this.btnEditBaseLine.Visible = false;
				this.btnEditWall.Visible = true;
				this.tbName.Enabled = true;
			}
			else
			{
				this.Text = "手工创建女儿墙";
				this.btnEditBaseLine.Visible = true;
				this.btnEditWall.Visible = false;
				this.tbName.Enabled = true;
			}
			this.InitParapetInfo();
			this.ReadData();
			this.UpdateCopingCmbState();
		}

		private void ParapetForm_FormClosing(object sender, FormClosingEventArgs e)
		{
			this.SaveData();
			if (base.DialogResult == DialogResult.Cancel)
			{
				return;
			}
			string str = "";
			if (!this.IsValidating(this.tbHeight.Text, 20.0, 10000.0, ref str))
			{
				MessageBox.Show("墙高" + str, "盈建科提示");
				e.Cancel = true;
				this.tbHeight.Focus();
				return;
			}
			if (!this.IsValidating(this.tbThickness.Text, 20.0, 5000.0, ref str))
			{
				MessageBox.Show("墙厚" + str, "盈建科提示");
				e.Cancel = true;
				this.tbThickness.Focus();
				return;
			}
			string text = this.tbName.Text.Trim();
			if (text.CompareTo("") == 0)
			{
				MessageBox.Show("名称不能为空", "盈建科提示");
				e.Cancel = true;
				this.tbName.Focus();
				return;
			}
			double val = 0.0;
			if (this.HasSameNameWithWallType(text, ref val))
			{
				double val2 = Convert.ToDouble(this.m_StrThickness);
				if (!Geometry.IsEqual(val, val2))
				{
					string str2 = val.ToString("f0");
					MessageBox.Show("文档中存在同名厚度为" + str2 + "mm的墙类型，请重新命名或者修改现有墙厚。", "盈建科提示");
					e.Cancel = true;
					this.tbName.Focus();
				}
			}
		}

		private bool HasSameNameWithWallType(string typeName, ref double oldThickness)
		{
			typeName = typeName.Trim();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Doc);
			ICollection<Element> collection = filteredElementCollector.OfClass(typeof(WallType)).ToElements();
			foreach (Element element in collection)
			{
				WallType wallType = element as WallType;
				if (wallType.Name.CompareTo(typeName) == 0)
				{
					oldThickness = AssistFunc.feetToMM(wallType.Width);
					return true;
				}
			}
			return false;
		}

		private void ReadData()
		{
			string tempPath = Path.GetTempPath();
			string path = tempPath + "ParapetForm.dat";
			if (!File.Exists(path))
			{
				base.StartPosition = FormStartPosition.CenterScreen;
				this.tbName.Text = "女儿墙-120";
				this.m_StrHeight = "500";
				this.m_StrThickness = "120";
				this.tbHeight.Text = this.m_StrHeight;
				this.tbThickness.Text = this.m_StrThickness;
				this.chkbCoping.Checked = true;
				this.cmbCoping.SelectedIndex = 0;
				return;
			}
			base.StartPosition = FormStartPosition.Manual;
			FileStream fileStream = new FileStream(path, FileMode.Open);
			StreamReader streamReader = new StreamReader(fileStream);
			streamReader.BaseStream.Seek(0L, SeekOrigin.Begin);
			int x = Convert.ToInt32(streamReader.ReadLine());
			int y = Convert.ToInt32(streamReader.ReadLine());
			base.Location = new System.Drawing.Point(x, y);
			this.tbName.Text = streamReader.ReadLine();
			this.m_StrHeight = streamReader.ReadLine();
			this.m_StrThickness = streamReader.ReadLine();
			this.tbHeight.Text = this.m_StrHeight;
			this.tbThickness.Text = this.m_StrThickness;
			this.chkbCoping.Checked = Convert.ToBoolean(streamReader.ReadLine());
			this.cmbCoping.SelectedIndex = Convert.ToInt32(streamReader.ReadLine());
			streamReader.Close();
			fileStream.Close();
		}

		public void SaveData()
		{
			string tempPath = Path.GetTempPath();
			string path = tempPath + "ParapetForm.dat";
			FileStream fileStream = new FileStream(path, FileMode.Create);
			StreamWriter streamWriter = new StreamWriter(fileStream);
			streamWriter.WriteLine(base.Location.X);
			streamWriter.WriteLine(base.Location.Y);
			streamWriter.WriteLine(this.tbName.Text);
			streamWriter.WriteLine(this.m_StrHeight);
			streamWriter.WriteLine(this.m_StrThickness);
			streamWriter.WriteLine(this.chkbCoping.Checked);
			streamWriter.WriteLine(this.cmbCoping.SelectedIndex);
			streamWriter.Flush();
			streamWriter.Close();
			fileStream.Close();
		}

		private void btnEditBaseLine_Click(object sender, EventArgs e)
		{
			this.m_ResultStyle = ParapetForm.FormResultStyle.FRS_BASELINE;
		}

		private void btnEditWall_Click(object sender, EventArgs e)
		{
			this.m_ResultStyle = ParapetForm.FormResultStyle.FRS_WALL;
		}

		private void btnOk_Click(object sender, EventArgs e)
		{
			this.m_ResultStyle = ParapetForm.FormResultStyle.FRS_OK;
		}

		private void chkbCoping_CheckedChanged(object sender, EventArgs e)
		{
			this.UpdateCopingCmbState();
			this.Refresh();
		}

		private void UpdateCopingCmbState()
		{
			if (this.chkbCoping.Checked)
			{
				this.cmbCoping.Enabled = true;
			}
			else
			{
				this.cmbCoping.Enabled = false;
			}
			this.btnLoadShape.Enabled = this.chkbCoping.Checked;
			this.btnRemove.Enabled = (this.cmbCoping.SelectedIndex > 3 && this.chkbCoping.Checked);
		}

		private void cmbCoping_SelectedIndexChanged(object sender, EventArgs e)
		{
			this.UpdateCopingCmbState();
			this.Refresh();
		}

		private void tbHeight_TextChanged(object sender, EventArgs e)
		{
			string text = "";
			if (!this.IsValidating(this.tbHeight.Text, 1.0, 10000.0, ref text))
			{
				this.tbHeight.Text = this.m_StrHeight;
				return;
			}
			this.m_StrHeight = this.tbHeight.Text;
			this.Refresh();
		}

		private void tbThickness_TextChanged(object sender, EventArgs e)
		{
			string text = "";
			if (!this.IsValidating(this.tbThickness.Text, 1.0, 10000.0, ref text))
			{
				this.tbThickness.Text = this.m_StrThickness;
				return;
			}
			this.m_StrThickness = this.tbThickness.Text;
			this.Refresh();
		}

		private bool IsValidating(string numStr, double minRange, double maxRange, ref string message)
		{
			try
			{
				if (numStr.Trim().CompareTo("") == 0)
				{
					return false;
				}
				if (numStr.Length > 1)
				{
					string text = numStr.Substring(0, 1);
					if (text.CompareTo("0") == 0)
					{
						return false;
					}
				}
				double val = Convert.ToDouble(numStr);
				if (Geometry.LessThan(val, minRange))
				{
					message = "数值值不能小于" + minRange.ToString("f0") + "mm";
					return false;
				}
				if (Geometry.GreaterThan(val, maxRange))
				{
					message = "数值值不能大于" + minRange.ToString("f0") + "mm";
					return false;
				}
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private void btnLoadShape_Click(object sender, EventArgs e)
		{
			OpenFileDialog openFileDialog = new OpenFileDialog();
			openFileDialog.Multiselect = true;
			openFileDialog.Title = "请选择压顶族文件";
			openFileDialog.Filter = "所有文件(*.rfa)|*.rfa";
			if (openFileDialog.ShowDialog() == DialogResult.OK)
			{
				foreach (string text in openFileDialog.FileNames)
				{
					string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
					if (!this.cmbCoping.Items.Cast<string>().Contains(fileNameWithoutExtension))
					{
						if (!this.IsValidSweepProfileCategory(text))
						{
							YJKMessageBox.Show("不是有效的轮廓族!");
						}
						else if (!this.IsValidSweepProfile(text))
						{
							YJKMessageBox.Show("族插入点不在轮廓底面!");
						}
						else
						{
							this.cmbCoping.Items.Add(fileNameWithoutExtension);
							string destFileName = ParapetForm.InitUserParapetFilePathWithVersion() + "\\" + fileNameWithoutExtension + ".rfa";
							File.Copy(text, destFileName, false);
						}
					}
				}
			}
		}

		private void btnRemove_Click(object sender, EventArgs e)
		{
			try
			{
				string text = this.cmbCoping.SelectedItem.ToString();
				if (this.IsWallSweepProfileSymbolActive(text))
				{
					YJKMessageBox.Show("族正在被使用, 无法执行删除操作!");
				}
				else
				{
					YJKMessageBox.Show("相应族文件也将被删除!");
					string path = ParapetForm.InitUserParapetFilePathWithVersion() + "\\" + text + ".rfa";
					File.Delete(path);
					int num = this.cmbCoping.SelectedIndex;
					this.cmbCoping.Items.RemoveAt(num);
					num = this.cmbCoping.Items.Count - 1;
					if (num == -1)
					{
						num = 0;
					}
					this.cmbCoping.SelectedIndex = num;
					Family sweepProfileFamily = this.GetSweepProfileFamily(text);
					if (sweepProfileFamily != null)
					{
						Transaction transaction = new Transaction(this.m_Doc, "DeleteFamily");
						try
						{
							transaction.Start();
							this.m_Doc.Delete(sweepProfileFamily.Id);
							transaction.Commit();
						}
						catch
						{
							transaction.RollBack();
						}
					}
				}
			}
			catch
			{
				YJKMessageBox.Show("压顶族删除失败!");
			}
		}

		private FamilySymbol GetSweepProfileSymbol(string strFamilyName)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Doc);
			return (from FamilySymbol e in filteredElementCollector.OfClass(typeof(FamilySymbol)).OfCategory(BuiltInCategory.OST_ProfileFamilies)
			where e.Family.Name == strFamilyName
			select e).FirstOrDefault<FamilySymbol>();
		}

		private Family GetSweepProfileFamily(string strFamilyName)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Doc);
			return (from e in filteredElementCollector.OfClass(typeof(Family)).OfType<Family>()
			where e.FamilyCategory.Id.IntegerValue == -2003000
			where e.Name == strFamilyName
			select e).FirstOrDefault<Family>();
		}

		private bool IsWallSweepProfileSymbolActive(string strFamilyName)
		{
			FamilySymbol symbol = this.GetSweepProfileSymbol(strFamilyName);
			if (symbol != null)
			{
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Doc);
				WallSweep wallSweep = (from WallSweep e in filteredElementCollector.OfClass(typeof(WallSweep))
				where e.GetWallSweepInfo().ProfileId == symbol.Id
				select e).FirstOrDefault<WallSweep>();
				return wallSweep != null;
			}
			return false;
		}

		private bool IsValidSweepProfileCategory(string strFilePathName)
		{
			Transaction transaction = new Transaction(this.m_Doc, "LoadProfileFamilyTemp");
			try
			{
				transaction.Start();
				Family family = null;
				if (this.m_Doc.LoadFamily(strFilePathName, out family))
				{
					Category familyCategory = family.FamilyCategory;
					return familyCategory.Id.IntegerValue == -2003000;
				}
			}
			catch
			{
			}
			finally
			{
				transaction.RollBack();
			}
			return false;
		}

		private bool IsValidSweepProfile(string strFilePathName)
		{
			Document document = null;
			try
			{
				this.m_Doc.Application.OpenDocumentFile(strFilePathName);
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
				List<CurveElement> list = filteredElementCollector.OfClass(typeof(CurveElement)).Cast<CurveElement>().ToList<CurveElement>();
				foreach (CurveElement curveElement in list)
				{
					if (Geometry.LessThan(curveElement.GeometryCurve.GetEndPoint(0).Y, 0.001, 0.0001) || Geometry.LessThan(curveElement.GeometryCurve.GetEndPoint(1).Y, 0.001, 0.0001))
					{
						return false;
					}
				}
			}
			catch
			{
			}
			finally
			{
				if (document != null)
				{
					document.Close(false);
				}
			}
			return true;
		}

		private Dictionary<string, List<Curve>> mapFamilyName2Cvs = new Dictionary<string, List<Curve>>();

		private ExternalCommandData m_cmdData;

		private Document m_Doc;

		private ParapetForm.FormStyle m_FormStyle = ParapetForm.FormStyle.FS_CREATE;

		private ParapetForm.FormResultStyle m_ResultStyle = ParapetForm.FormResultStyle.FRS_OK;

        private Parapet.Previewer.Previewer m_MainPreviewer;

		private ParapetProfileDrawingKit m_ParapetProfileDrawingKit = new ParapetProfileDrawingKit();

		private string m_StrHeight = "";

		private string m_StrThickness = "";

		private static string strFamilyFolderName = "Templates";

		private static string strFamilyDocFileName = "HY压顶.rfa";

		private class ParapetFamilySymbolData
		{
			public string FamilySymbolName { get; set; }

			public string FamilyDocPathName { get; set; }

			public bool IsUserItem { get; set; }
		}

		public class ParapetData
		{
			public string TypeName { get; set; }

			public double Height { get; set; }

			public double Thickness { get; set; }

			public bool HasCoping { get; set; }

			public int CopingStyleIndex { get; set; }

			public string CopingStyleName { get; set; }

			public List<Curve> UserProfileCvs { get; set; }

			public ParapetData()
			{
			}

			public ParapetData(ParapetForm.ParapetData other)
			{
				this.TypeName = other.TypeName;
				this.Height = other.Height;
				this.Thickness = other.Thickness;
				this.HasCoping = other.HasCoping;
				this.CopingStyleIndex = other.CopingStyleIndex;
				this.CopingStyleName = other.CopingStyleName;
				this.UserProfileCvs = other.UserProfileCvs;
			}
		}

		public enum FormStyle
		{
			FS_CREATE = 1,
			FS_EDITBASELINE,
			FS_EDITWALL
		}

		public enum FormResultStyle
		{
			FRS_OK = 1,
			FRS_BASELINE,
			FRS_WALL
		}
	}
}
